#include <iostream>
#include <memory>

//建造者模式  主要用于复杂对象的创建
//由四个核心类实现
//1.抽象产品类
//2.具体产品类 ： 一个具体的产品对象类
//3.抽象Builder类，创建一个产品对象所需要的各个部件的抽象接口
//4.具体Builder类，实现抽象接口，国建各个部件
//5. 指挥者Director类： 统一组件过程，提供给调用者使用，通过指挥来构造产品

//抽象电脑类
class Computer
{
public:
    using ptr = std::shared_ptr<Computer>;
    Computer(){}
    void setBoard(const std::string& board){_board = board;}
    void setDisplay(const std::string& display){_display = display;}
    virtual void setOs() = 0;
    std::string toString(){
        std::string computer = "Computer:{\n";
        computer += "\tboard=" +_board + ",\n"; 
        computer += "\tdisplay=" +_display + ",\n"; 
        computer += "\tOs=" +_os + ",\n"; 
        computer += "}\n";
        return computer;
    }

protected:
    std::string _board;
    std::string _display;
    std::string _os;
};


//具体产品类
class MacBook : public Computer
{
public:
    using ptr = std::shared_ptr<MacBook>;
    MacBook(){}
    virtual void setOs()
    {
        _os = "Max Os X12";
    }
};

//抽象建造者类，包含创建一个产品对象的各个部件的抽象接口
class Builder
{
public:
    using ptr = std::shared_ptr<Builder>;
    virtual void buildBoard(const std::string& board) = 0;
    virtual void buildDisplay(const std::string& display) = 0;
    virtual void buildOs() =0;
    virtual Computer::ptr build() = 0;
};

//具体产品的具体建造类 ，实现抽象接口，构建和各个部件
class MacBookBuilder : public Builder
{
public:
    using ptr = std::shared_ptr<MacBookBuilder>;
    MacBookBuilder():_computer(new MacBook()) {}
    virtual void buildBoard(const std::string & board)
    {
        _computer->setBoard(board);
    }

    virtual void buildDisplay(const std::string& display)
    {
        _computer->setDisplay(display);
    }

    virtual void buildOs()
    {
        _computer->setOs();
    }
    virtual Computer::ptr build()
    {
        return _computer;
    }


private:
    Computer::ptr _computer;
};

//指挥者类，提供给调用者使用，通过指挥者来构造复杂的对象
class Director
{
public:
    Director(Builder* builder) :_builder(builder)
    {}

    void construct(const std::string& board,const std::string& display)
    {
        _builder->buildBoard(board);
        _builder->buildDisplay(display);
        _builder->buildOs();
    }



private:
    Builder::ptr _builder;
};


//代理者模式 代理控制对其他对象的访问
//以租房为例，让代理对象控制源对象的引用。 

class RentHouse
{
public:
    virtual void rentHouse() =0;
};

//房东类 Landlord 是房东的意思
class Landlord : public RentHouse
{
public:
    void rentHouse()
    {
        std::cout << "将房子租出去\n";
    }
};


//中介代理费用： 对房子进行功能加强，实现租房以外的其他功能
class Intermediary :public RentHouse
{
public:
    void rentHouse() override
    {
        std::cout << "发布招租启示\n";
        std::cout << "待人看房\n";
        _landlord.rentHouse();
        std::cout << "负责租后维修\n";
    }

private:
    Landlord _landlord;
};


int main()
{
    Builder* builder = new MacBookBuilder();
    std::unique_ptr<Director> pd(new Director(builder));
    pd->construct("英特尔主板", "VOC显示器");
    Computer::ptr computer = builder->build();
    std::cout <<computer->toString() << std::endl; 


    Intermediary intermediary;
    intermediary.rentHouse();

    return 0;
}

